```html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JDBC事务管理全解析 | 技术小馆</title>
    <link href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <link href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        :root {
            --primary: #2563eb;
            --primary-dark: #1d4ed8;
            --secondary: #7c3aed;
            --accent: #d946ef;
            --text: #1e293b;
            --light-text: #64748b;
            --bg: #f8fafc;
            --card-bg: #ffffff;
        }
        
        body {
            font-family: 'Noto Sans SC', 'Noto Serif SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            color: var(--text);
            background-color: var(--bg);
            line-height: 1.6;
        }
        
        h1, h2, h3, h4, h5, h6 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
            margin-top: 1.5em;
            margin-bottom: 0.8em;
            color: var(--text);
        }
        
        h1 {
            font-size: 2.5rem;
            font-weight: 700;
            line-height: 1.2;
            border-bottom: 2px solid var(--primary);
            padding-bottom: 0.3em;
        }
        
        h2 {
            font-size: 2rem;
            border-left: 4px solid var(--primary);
            padding-left: 0.8rem;
        }
        
        h3 {
            font-size: 1.5rem;
        }
        
        p {
            margin-bottom: 1.2em;
            font-size: 1.05rem;
        }
        
        a {
            color: var(--primary);
            text-decoration: none;
            transition: color 0.2s;
        }
        
        a:hover {
            color: var(--primary-dark);
            text-decoration: underline;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 2rem;
        }
        
        .hero {
            background: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
            color: white;
            padding: 5rem 0;
            margin-bottom: 4rem;
            border-radius: 0 0 20px 20px;
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
        }
        
        .hero-content {
            max-width: 800px;
            margin: 0 auto;
            text-align: center;
        }
        
        .hero-title {
            font-size: 3rem;
            font-weight: 700;
            margin-bottom: 1.5rem;
            text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        
        .hero-subtitle {
            font-size: 1.25rem;
            opacity: 0.9;
            max-width: 700px;
            margin: 0 auto 2rem;
        }
        
        .card {
            background-color: var(--card-bg);
            border-radius: 12px;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
            padding: 2rem;
            margin-bottom: 3rem;
            transition: transform 0.3s, box-shadow 0.3s;
        }
        
        .card:hover {
            transform: translateY(-5px);
            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
        }
        
        .card-title {
            font-size: 1.5rem;
            margin-top: 0;
            margin-bottom: 1.5rem;
            color: var(--primary);
        }
        
        .code-block {
            background-color: #1e293b;
            color: #f8fafc;
            border-radius: 8px;
            padding: 1.5rem;
            overflow-x: auto;
            margin: 1.5rem 0;
            font-family: 'Courier New', Courier, monospace;
            line-height: 1.5;
        }
        
        .code-block .keyword {
            color: #60a5fa;
        }
        
        .code-block .string {
            color: #34d399;
        }
        
        .code-block .comment {
            color: #94a3b8;
            font-style: italic;
        }
        
        .code-block .method {
            color: #f472b6;
        }
        
        .code-block .class {
            color: #f59e0b;
        }
        
        .icon-box {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 48px;
            height: 48px;
            border-radius: 12px;
            background-color: rgba(37, 99, 235, 0.1);
            color: var(--primary);
            margin-right: 1rem;
            flex-shrink: 0;
        }
        
        .feature-item {
            display: flex;
            margin-bottom: 1.5rem;
        }
        
        .feature-content {
            flex: 1;
        }
        
        .feature-title {
            font-weight: 600;
            margin-top: 0;
            margin-bottom: 0.5rem;
        }
        
        .divider {
            height: 1px;
            background-color: #e2e8f0;
            margin: 2rem 0;
        }
        
        .highlight {
            background-color: rgba(251, 191, 36, 0.2);
            padding: 0.2em 0.4em;
            border-radius: 4px;
        }
        
        .quote {
            border-left: 4px solid var(--primary);
            padding-left: 1.5rem;
            margin: 1.5rem 0;
            font-style: italic;
            color: var(--light-text);
        }
        
        .footer {
            background-color: #1e293b;
            color: white;
            padding: 3rem 0;
            margin-top: 4rem;
        }
        
        .footer-content {
            display: flex;
            justify-content: space-between;
            align-items: center;
            max-width: 1200px;
            margin: 0 auto;
            padding: 0 2rem;
        }
        
        .footer-link {
            color: #94a3b8;
            transition: color 0.2s;
        }
        
        .footer-link:hover {
            color: #e2e8f0;
            text-decoration: underline;
        }
        
        .badge {
            display: inline-block;
            padding: 0.25rem 0.75rem;
            border-radius: 9999px;
            font-size: 0.875rem;
            font-weight: 500;
            margin-right: 0.5rem;
            margin-bottom: 0.5rem;
        }
        
        .badge-primary {
            background-color: #dbeafe;
            color: var(--primary);
        }
        
        .badge-secondary {
            background-color: #ede9fe;
            color: var(--secondary);
        }
        
        .badge-accent {
            background-color: #f5d0fe;
            color: var(--accent);
        }
        
        .image-container {
            margin: 2rem 0;
            text-align: center;
        }
        
        .image-container img {
            max-width: 100%;
            height: auto;
            border-radius: 8px;
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
        }
        
        @media (max-width: 768px) {
            .container {
                padding: 0 1rem;
            }
            
            .hero {
                padding: 3rem 0;
            }
            
            .hero-title {
                font-size: 2.25rem;
            }
            
            h1 {
                font-size: 2rem;
            }
            
            h2 {
                font-size: 1.75rem;
            }
        }
    </style>
</head>
<body>
    <div class="hero">
        <div class="hero-content">
            <h1 class="hero-title">JDBC事务管理全解析</h1>
            <p class="hero-subtitle">深入理解数据库事务的ACID特性，掌握JDBC事务控制的最佳实践</p>
            <div class="flex justify-center space-x-4">
                <span class="badge badge-primary"><i class="fas fa-database mr-1"></i> JDBC</span>
                <span class="badge badge-secondary"><i class="fas fa-code mr-1"></i> Java</span>
                <span class="badge badge-accent"><i class="fas fa-shield-alt mr-1"></i> ACID</span>
            </div>
        </div>
    </div>
    
    <div class="container">
        <article>
            <section class="mb-12">
                <div class="card">
                    <h2>JDBC使用事务</h2>
                    <p>在实际开发中，数据库操作是不可避免的，而事务机制是确保数据库操作的一致性、可靠性和完整性的关键工具。事务不仅仅是对数据操作的封装，它还能保证一系列操作要么全部成功，要么全部失败，防止因中间操作失败导致数据的不一致。了解并掌握事务的使用，是每个开发者在进行数据库操作时必备的技能。</p>
                    
                    <div class="image-container">
                        <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1735969416360-8e559520-171e-49b9-94da-582a45e7940a.png" alt="JDBC事务示意图">
                    </div>
                    
                    <p>在 JDBC 中，事务的默认行为是自动提交，也就是说每执行一条 SQL 语句，JDBC 都会自动提交它的执行结果。而在某些复杂的操作中，我们往往需要将多个 SQL 语句作为一个整体来执行，这时我们就需要手动管理事务的提交和回滚，确保事务操作的原子性和一致性。</p>
                </div>
            </section>
            
            <section class="mb-12">
                <div class="card">
                    <h2>事务的基本概念</h2>
                    <p>事务（Transaction）是数据库管理系统（DBMS）中的一个重要概念，它代表了一组操作的集合，这些操作要么全部执行成功，要么全部回滚。事务保证了数据库操作的<strong>一致性</strong>、<strong>完整性</strong>和<strong>可靠性</strong>，确保即使在系统故障时，数据也不会处于不一致的状态。</p>
                    
                    <div class="image-container">
                        <img src="https://cdn.nlark.com/yuque/0/2025/png/21449790/1735969443814-abcb4eaf-152d-4ef4-9c78-f10765106bd9.png" alt="事务示意图">
                    </div>
                    
                    <p>在数据库操作中，事务常用于以下场景：多个数据库操作需要保证原子性（即要么全部执行，要么全部不执行）；多个操作之间需要保持数据的一致性；以及当发生错误时需要回滚所有的操作，以避免部分操作导致数据不一致。</p>
                    
                    <h3>ACID 特性</h3>
                    <p>事务有四大基本特性，统称为 <strong>ACID</strong> 特性，确保事务的可靠性和一致性：</p>
                    
                    <div class="feature-item">
                        <div class="icon-box">
                            <i class="fas fa-atom"></i>
                        </div>
                        <div class="feature-content">
                            <h4 class="feature-title">原子性（Atomicity）</h4>
                            <p>事务中的操作要么全部成功，要么全部失败。即事务是不可分割的单位，一旦开始，就必须完全执行完毕。如果出现错误，系统将会回滚事务中的所有操作，恢复到事务开始前的状态。</p>
                        </div>
                    </div>
                    
                    <div class="feature-item">
                        <div class="icon-box">
                            <i class="fas fa-link"></i>
                        </div>
                        <div class="feature-content">
                            <h4 class="feature-title">一致性（Consistency）</h4>
                            <p>事务开始前和结束后，数据库的状态必须一致。即事务执行之前，数据库是处于一致性状态的，执行完毕后，数据库也应当保持一致性状态。任何事务都不能破坏数据的完整性约束，如主键、外键等。</p>
                        </div>
                    </div>
                    
                    <div class="feature-item">
                        <div class="icon-box">
                            <i class="fas fa-user-shield"></i>
                        </div>
                        <div class="feature-content">
                            <h4 class="feature-title">隔离性（Isolation）</h4>
                            <p>一个事务的执行不应当受到其他事务的干扰。事务的隔离性保证了多个事务并发执行时，彼此之间不会互相影响。数据库支持不同的隔离级别，从而在性能和一致性之间进行权衡。</p>
                        </div>
                    </div>
                    
                    <div class="feature-item">
                        <div class="icon-box">
                            <i class="fas fa-save"></i>
                        </div>
                        <div class="feature-content">
                            <h4 class="feature-title">持久性（Durability）</h4>
                            <p>一旦事务提交，事务对数据库的修改就是永久性的，甚至在系统崩溃的情况下也能保证数据的持久性。提交后的事务所做的修改将被保存在数据库中，并且不会丢失。</p>
                        </div>
                    </div>
                </div>
            </section>
            
            <section class="mb-12">
                <div class="card">
                    <h2>JDBC中的事务控制</h2>
                    <p>在 JDBC 中，事务控制是通过 <code>Connection</code> 对象来管理的。默认情况下，JDBC 连接会自动提交每个 SQL 语句的执行结果，但在很多场景下，尤其是涉及多个 SQL 操作时，我们需要手动控制事务的提交和回滚。JDBC 提供了一些方法，允许开发者显式地管理事务，确保操作的一致性、原子性和完整性。</p>
                    
                    <h3>自动提交模式（Auto-commit）</h3>
                    <p>默认情况下，JDBC 会将每个 SQL 语句的执行视为一个独立的事务，并在语句执行后立即提交。这是 JDBC 的 <strong>自动提交模式</strong>。</p>
                    
                    <ul class="list-disc pl-6 mb-4">
                        <li><strong>开启自动提交模式</strong>：<code>Connection.setAutoCommit(true)</code></li>
                        <li><strong>关闭自动提交模式</strong>：<code>Connection.setAutoCommit(false)</code></li>
                    </ul>
                    
                    <p>当 <code>setAutoCommit(false)</code> 时，JDBC 会等待显式调用 <code>commit()</code> 来提交事务。这使得多个 SQL 操作可以在一个事务中执行，保证操作的原子性。</p>
                    
                    <h3>提交事务（Commit）</h3>
                    <p>当事务中的所有操作都成功时，调用 <code>commit()</code> 方法来提交事务，使得所有操作的结果被永久保存到数据库中。</p>
                    
                    <div class="code-block">
                        <span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;<span class="comment">// 执行SQL操作...</span><br>
                        &nbsp;&nbsp;conn.<span class="method">commit</span>(); <span class="comment">// 提交事务</span><br>
                        } <span class="keyword">catch</span> (SQLException e) {<br>
                        &nbsp;&nbsp;conn.<span class="method">rollback</span>(); <span class="comment">// 出错时回滚</span><br>
                        }
                    </div>
                    
                    <h3>回滚事务（Rollback）</h3>
                    <p>如果在事务执行过程中发生异常，或者希望撤销某些操作，可以使用 <code>rollback()</code> 方法回滚事务。回滚会撤销自事务开始以来的所有数据库操作。</p>
                    
                    <div class="code-block">
                        <span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;<span class="comment">// 执行SQL操作...</span><br>
                        &nbsp;&nbsp;conn.<span class="method">commit</span>();<br>
                        } <span class="keyword">catch</span> (SQLException e) {<br>
                        &nbsp;&nbsp;<span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">rollback</span>(); <span class="comment">// 回滚事务</span><br>
                        &nbsp;&nbsp;} <span class="keyword">catch</span> (SQLException ex) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;ex.<span class="method">printStackTrace</span>();<br>
                        &nbsp;&nbsp;}<br>
                        }
                    </div>
                    
                    <h3>事务隔离级别</h3>
                    <p>为了控制事务之间的并发执行，数据库提供了不同的事务隔离级别。隔离级别决定了一个事务对另一个事务的可见性和干扰程度。</p>
                    
                    <div class="mermaid">
                        graph TD
                            A[事务隔离级别] --> B[READ_UNCOMMITTED]
                            A --> C[READ_COMMITTED]
                            A --> D[REPEATABLE_READ]
                            A --> E[SERIALIZABLE]
                            B -->|最低级别,脏读| F[性能最好]
                            C -->|防止脏读| G[平衡选择]
                            D -->|防止不可重复读| H[较高隔离]
                            E -->|最高级别| I[性能最差]
                    </div>
                    
                    <p>JDBC 支持以下四个事务隔离级别，使用 <code>Connection.setTransactionIsolation()</code> 方法设置：</p>
                    
                    <div class="code-block">
                        <span class="comment">// 设置隔离级别为READ_COMMITTED</span><br>
                        conn.<span class="method">setTransactionIsolation</span>(Connection.<span class="class">TRANSACTION_READ_COMMITTED</span>);
                    </div>
                    
                    <h3>JDBC 事务管理最佳实践</h3>
                    <ul class="list-disc pl-6">
                        <li><strong>关闭自动提交</strong>：在处理多个 SQL 语句时，关闭自动提交以便手动控制事务的提交和回滚。</li>
                        <li><strong>及时提交事务</strong>：在事务成功完成时，尽早调用 <code>commit()</code> 提交事务，避免长时间占用数据库连接。</li>
                        <li><strong>异常处理</strong>：如果事务中的任何操作失败，应该立即回滚事务，确保数据库的状态不被破坏。</li>
                        <li><strong>使用保存点</strong>：在复杂事务中，可以使用保存点来实现部分回滚，提高事务的灵活性。</li>
                        <li><strong>避免长时间持有事务</strong>：长时间运行的事务可能会锁住数据库资源，影响系统性能。应该尽量缩短事务的执行时间。</li>
                    </ul>
                </div>
            </section>
            
            <section class="mb-12">
                <div class="card">
                    <h2>案例：银行转账系统</h2>
                    <p>下面是一个使用 JDBC 进行事务控制的示例代码。该示例模拟了一个银行转账的场景，涉及两个账户之间的资金转移。我们通过手动控制事务来保证转账操作的原子性，确保要么全部成功，要么全部失败。</p>
                    
                    <div class="quote">
                        <p>假设我们有两个表 <code>accounts</code>，每个账户有一个 <code>id</code> 和 <code>balance</code> 字段</p>
                    </div>
                    
                    <div class="code-block">
                        <span class="keyword">CREATE TABLE</span> accounts (<br>
                        &nbsp;&nbsp;id <span class="class">INT</span> <span class="method">PRIMARY KEY</span>,<br>
                        &nbsp;&nbsp;balance <span class="class">DECIMAL</span>(10, 2)<br>
                        );
                    </div>
                    
                    <h3>完整代码示例</h3>
                    <div class="code-block">
                        <span class="keyword">import</span> java.sql.Connection;<br>
                        <span class="keyword">import</span> java.sql.DriverManager;<br>
                        <span class="keyword">import</span> java.sql.PreparedStatement;<br>
                        <span class="keyword">import</span> java.sql.SQLException;<br><br>
                        
                        <span class="keyword">public class</span> <span class="class">BankTransferDemo</span> {<br><br>
                        
                        &nbsp;&nbsp;<span class="keyword">public static void</span> <span class="method">main</span>(String[] args) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 数据库连接信息</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;String url = <span class="string">"jdbc:mysql://localhost:3306/mydb"</span>;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;String user = <span class="string">"root"</span>;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;String password = <span class="string">"password"</span>;<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;Connection conn = <span class="keyword">null</span>;<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 获取数据库连接</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn = DriverManager.<span class="method">getConnection</span>(url, user, password);<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 关闭自动提交，手动控制事务</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">setAutoCommit</span>(<span class="keyword">false</span>);<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 账户转账：从账户1转账到账户2</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">double</span> amount = 100.00;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span> fromAccount = 1;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span> toAccount = 2;<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 执行转账操作：首先从账户1扣除金额</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String withdrawSql = <span class="string">"UPDATE accounts SET balance = balance - ? WHERE id = ?"</span>;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span> (PreparedStatement withdrawStmt = conn.<span class="method">prepareStatement</span>(withdrawSql)) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;withdrawStmt.<span class="method">setDouble</span>(1, amount);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;withdrawStmt.<span class="method">setInt</span>(2, fromAccount);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span> rowsUpdated = withdrawStmt.<span class="method">executeUpdate</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span> (rowsUpdated == 0) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">throw new</span> SQLException(<span class="string">"转账失败：账户1不存在或余额不足"</span>);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 然后将金额加到账户2</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String depositSql = <span class="string">"UPDATE accounts SET balance = balance + ? WHERE id = ?"</span>;<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span> (PreparedStatement depositStmt = conn.<span class="method">prepareStatement</span>(depositSql)) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depositStmt.<span class="method">setDouble</span>(1, amount);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depositStmt.<span class="method">setInt</span>(2, toAccount);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span> rowsUpdated = depositStmt.<span class="method">executeUpdate</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span> (rowsUpdated == 0) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">throw new</span> SQLException(<span class="string">"转账失败：账户2不存在"</span>);<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 提交事务，保存更改</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">commit</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="method">out</span>.<span class="method">println</span>(<span class="string">"转账成功！"</span>);<br><br>
                        
                        &nbsp;&nbsp;&nbsp;&nbsp;} <span class="keyword">catch</span> (SQLException e) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 如果发生异常，回滚事务</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span> (conn != <span class="keyword">null</span>) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">rollback</span>();  <span class="comment">// 回滚事务</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.<span class="method">out</span>.<span class="method">println</span>(<span class="string">"事务已回滚： "</span> + e.<span class="method">getMessage</span>());<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span class="keyword">catch</span> (SQLException rollbackException) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rollbackException.<span class="method">printStackTrace</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.<span class="method">printStackTrace</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;} <span class="keyword">finally</span> {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">// 恢复自动提交模式，并关闭连接</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span> (conn != <span class="keyword">null</span>) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span> {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">setAutoCommit</span>(<span class="keyword">true</span>);  <span class="comment">// 恢复自动提交</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.<span class="method">close</span>();  <span class="comment">// 关闭连接</span><br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span class="keyword">catch</span> (SQLException e) {<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.<span class="method">printStackTrace</span>();<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;&nbsp;&nbsp;}<br>
                        &nbsp;&nbsp;}<br>
                        }
                    </div>
                    
                    <h3>代码说明</h3>
                    <ol class="list-decimal pl-6">
                        <li><strong>关闭自动提交模式</strong>：通过 <code>conn.setAutoCommit(false)</code>，我们关闭了 JDBC 的自动提交功能，事务需要手动提交。</li>
                        <li><strong>执行 SQL 操作</strong>：在转账过程中，我们首先更新账户1的余额，然后更新账户2的余额。</li>
                        <li><strong>提交事务</strong>：当所有操作成功完成时，调用 <code>conn.commit()</code> 提交事务。</li>
                        <li><strong>异常处理和回滚</strong>：如果在转账过程中发生任何异常，我们会捕获该异常，并使用 <code>conn.rollback()</code> 回滚事务。</li>
                    </ol>
                </div>
            </section>
        </article>
    </div>
    
    <footer class="footer">
        <div class="footer-content">
            <div>
                <p class="text-lg font-medium">技术小馆</p>
                <p class="text-sm opacity-75">探索技术之美，分享知识之光</p>
            </div>
            <div>
                <a href="http://www.yuque.com/jtostring" class="footer-link">http://www.yuque.com/jtostring</a>
            </div>
        </div>
    </footer>
    
    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'dark',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true
            }
        });
    </script>
</body>
</html>
```